package com.shenfa.tools;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.regex.Pattern;

/**
 * 对基础类型进行封装处理
 * @author STEEL-CHINA
 * @date 2011-08-17
 */
public class SteelDataType {
	
	/**
	 * 判断一个对象是否为字节类型
	 * @param value 数据对象
	 * @return 是否字节类型 true:是;false:否.
	 */
	public static boolean isByte(Object value) {
		return value instanceof Byte;
	} // End isByte
	
	/**
	 * 判断一个对象是否为字符类型
	 * @param value 数据对象
	 * @return 是否字符类型 true:是;false:否.
	 */
	public static boolean isChar(Object value) {
		return value instanceof Character;
	} // End isChar
	
	/**
	 * 判断一个对象是否为短整型类型
	 * @param value 数据对象
	 * @return 是否短整型类型 true:是;false:否.
	 */
	public static boolean isShort(Object value) {
		return value instanceof Short;
	} // End isShort
	
	/**
	 * 判断一个对象是否为整型类型
	 * @param value 数据对象
	 * @return 是否整型类型 true:是;false:否.
	 */
	public static boolean isInt(Object value) {
		return value instanceof Integer;
	} // End isInt
	
	/**
	 * 判断一个对象是否为长整型类型
	 * @param value 数据对象
	 * @return 是否长整型类型 true:是;false:否.
	 */
	public static boolean isLong(Object value) {
		return value instanceof Long;
	} // End isLong
	
	/**
	 * 判断一个对象是否为单精度浮点类型
	 * @param value 数据对象
	 * @return 是否单精度浮点类型 true:是;false:否.
	 */
	public static boolean isFloat(Object value) {
		return value instanceof Float;
	} // End isFloat
	
	/**
	 * 判断一个对象是否为双精度浮点类型
	 * @param value 数据对象
	 * @return 是否双精度浮点类型 true:是;false:否.
	 */
	public static boolean isDouble(Object value) {
		return value instanceof Double;
	} // End isDouble
	
	/**
	 * 判断一个对象是否为布尔类型
	 * @param value 数据对象
	 * @return 是否布尔类型 true:是;false:否.
	 */
	public static boolean isBoolean(Object value) {
		return value instanceof Boolean;
	} // End isBoolean
	
	/**
	 * 判断一个对象是否为字符串类型
	 * @param value 数据对象
	 * @return 是否字符串类型 true:是;false:否.
	 */
	public static boolean isString(Object value) {
		return value instanceof String;
	} // End isString
	
	/**
	 * 判断一个对象是否为日期时间类型
	 * @param value 数据对象
	 * @return 是否日期时间类型 true:是;false:否.
	 */
	public static boolean isDate(Object value) {
		return value instanceof Date;
	} // End isDate
	
	/**
	 * 判断一个对象是否为日期时间 对象类型
	 * 符合Date、Calendar、GregorianCalendar
	 * @param value 数据对象
	 * @return 是否日期时间类型 true:是;false:否.
	 */
	public static boolean isDateObject(Object value) {
		return isDate(value) || value instanceof Calendar || value instanceof GregorianCalendar;
	} // End isDateObject
	
	/**
	 * 判断一个对象是否为数值类型
	 * @param value 数据对象
	 * @return 是否数值类型 true:是;false:否.
	 */
	public static boolean isNumber(Object value) {
		return isByte(value) || isShort(value)
				|| isInt(value) || isLong(value)
				|| isFloat(value) || isDouble(value);
	} // End isNumber

	/**
	 * 根据提供的对象获取字节数据
	 * 字节类型直接返回；
	 * 如果为数值数据，则按Double数据类型进行转换后取字节
	 * 如果为其它类型，则按Double转换规则进行转换取字节
	 * @param value 数据对象
	 * @return byte 获取字节数据
	 */
	public static byte getByte(Object value) {
		return isByte(value) ? (Byte)value : getDouble0(value).byteValue();
	} // End getByte
	
	/**
	 * 根据提供的对象获取字符数据
	 * 字符类型直接返回；
	 * 如果为数值数据，则按Double数据类型进行转换后取字节值转为字符
	 * 如果为其它类型，则按Double转换规则进行转换取字节值转为字符
	 * @param value 数据对象
	 * @return char 获取字符数据
	 */
	public static char getChar(Object value) {
		return isChar(value) ? (Character)value : (char)getDouble0(value).byteValue();
	} // End getChar
	
	/**
	 * 根据提供的对象获取短整型数据
	 * 短整型类型直接返回；
	 * 如果为数值数据，则按Double数据类型进行转换后取字节值转短整型
	 * 如果为其它类型，则按Double转换规则进行转换取字节值转为短整型
	 * @param value 数据对象
	 * @return char 获取短整型数据
	 */
	public static short getShort(Object value) {
		return isShort(value) ? (Short)value : getDouble0(value).shortValue();
	} // End getShort
	
	/**
	 * 根据提供的对象获取整型数据
	 * 整型类型直接返回；
	 * 如果为数值数据，则按Double数据类型进行转换后取字节值转整型
	 * 如果为其它类型，则按Double转换规则进行转换取字节值转为整型
	 * @param value 数据对象
	 * @return char 获取整型数据
	 */
	public static int getInt(Object value) {
		return isInt(value) ? (Integer)value : getDouble0(value).intValue();
	} // End getInt
	
	/**
	 * 根据提供的对象获取长整型数据
	 * 长整型类型直接返回；
	 * 如果为数值数据，则按Double数据类型进行转换后取字节值转长整型
	 * 如果为其它类型，则按Double转换规则进行转换取字节值转为长整型
	 * @param value 数据对象
	 * @return char 获取长整型数据
	 */
	public static long getLong(Object value) {
		return isLong(value) ? (Long)value : getDouble0(value).longValue();
	} // End getLong
	
	/**
	 * 根据提供的对象获取单精度浮点型数据
	 * 单精度浮点型类型直接返回；
	 * 如果为数值数据，则按Double数据类型进行转换后取字节值转单精度浮点型
	 * 如果为其它类型，则按Double转换规则进行转换取字节值转为单精度浮点型
	 * @param value 数据对象
	 * @return char 获取单精度浮点型数据
	 */
	public static float getFloat(Object value) {
		return isFloat(value) ? (Float)value : getDouble0(value).floatValue();
	} // End getFloat
	
	/**
	 * 根据提供的对象获取双精度浮点型数据
	 * 双精度浮点型类型直接返回；
	 * 如果为数值数据，则按Double数据类型进行转换后取字节值转双精度浮点型
	 * 如果为其它类型，则按Double转换规则进行转换取字节值转为双精度浮点型
	 * @param value 数据对象
	 * @return char 获取双精度浮点型数据
	 */
	public static double getDouble(Object value) {
		return isDouble(value) ? (Double)value : getDouble0(value).doubleValue();
	} // End getDouble
	
	/**
	 * 把可以转换为数值的数据类型进行转换。
	 * 字符类型取字符的编码值
	 * 字符串取数字字符串的转换结果,true=1;false=0
	 * 日期型取毫秒值
	 * 布尔值取1或0
	 * 无法转换则取0
	 * @param value 数据对象
	 * @return Double 转换后的数据对象
	 */
	private static Double getDouble0(Object value) {
		Double result;
		
		// Double则直接进行双精度转换
		if(isDouble(value)) {
			result = (Double)value;

		// 数值数据类型，进行Double解析
		} else if(isNumber(value)) {
			result = Double.parseDouble(value.toString());
			
		// 字符类型则取字符的编码值
		} else if(isChar(value)) {
			result = ((Character)value).charValue() + 0d;
			
		// 字符串则按数值字符串进行转换
		} else if(isString(value)) {
			String s = value.toString();
			if(Pattern.matches("[0-9]{1,32}([.]{1}[0-9]{1,19}){0,1}", s)) {
				result = Double.parseDouble(value.toString());
			} else if(s.equalsIgnoreCase("true")) {
				result = 1d;
			} else if(s.equalsIgnoreCase("false")) {
				result = 0d;
			} else {
				result = 0d;
			}
		
		// 日期类型则取毫秒值
		} else if(isDate(value)) {
			result = ((Date)value).getTime() + 0d;
		} else if(isDateObject(value)) {
			result = ((Calendar)value).getTime().getTime() + 0d;
			
		// 布尔值取真1；假0；
		} else if(isBoolean(value)) {
			result = ((Boolean)value).booleanValue() ? 1d : 0d;
		} else {
			result = 0d;
		}
		
		return result;
	} // End getDouble0
	
	/**
	 * 获取字符串
	 * 字符和数值类型，直接返回toString()
	 * 日期时间类型返回yyyy-mm-dd hh:mm:ss类型数据
	 * 布尔值返回true或false
	 * @param value 数据对象
	 * @return String 字符串数据
	 */
	public static String getString(Object value) {
		String result = "";
		
		if(isString(value)) {
			result = (String)value;
			
		// 布尔值取true或false
		} else if(isBoolean(value)) {
			result = ((Boolean)value).booleanValue() ? "true" : "false";
			
		// 日期类型取yyyy-mm-dd hh:mm:ss类型数据
		} else if(isDate(value) || isDateObject(value)) {
			result = new SimpleDateFormat(SteelDate.YYYY_MM_DD_HH_MM_SS).format(
					isDate(value) ? (Date)value : ((Calendar)value).getTime());
			
		// 其它数据类型取toString();
		} else {
			result = value.toString();
		}
		
		return result;
	} // End getString
	
	/**
	 * 获取布尔类型数据
	 * 转换规则：布尔值取原型
	 * 字符类型取Y、y、1为true；其余为false；
	 * 数值类型，大于0为true;其余为false;
	 * 字符串，true、y、1为true；其余为false;
	 * @param value 数据对象
	 * @return boolean 转换后的布尔值
	 */
	public static boolean getBoolean(Object value) {
		boolean result = false;
		
		// 布尔类型，取原型
		if(isBoolean(value)) {
			result = (Boolean)value;
			
		// 字符类型取Y、y、1为true；其余为false；
		} else if(isChar(value)) {
			char c = (Character)value;
			result = c == 'Y' || c == 'y' || c == '1' ? true : false;
			
		// 数值类型，大于0为true;其余为false;
		} else if(isNumber(value)) {
			result = getDouble0(value) > 0;
			
		// 字符串，true、y、1为true；其余为false;
		} else if(isString(value)) {
			String s = (String)value;
			result = s.equalsIgnoreCase("true") || s.equalsIgnoreCase("y") || s.equals("1");
		}
		
		return result;
	} // End getBoolean
	
	/**
	 * 获取日期类型数据
	 * 转换规则：日期类型返回原型
	 * 数值类型数据，以1970年1月1日以后的毫秒构建日期对象
	 * 字符类型，分数值型字符串和日期字符串构建
	 * 否则返回当前日期
	 * @param value 日期对象
	 * @return Date 转换后的日期对象
	 */
	public static Date getDate(Object value) {
		Date date;
		
		// 日期对象原型
		if(isDate(value)) {
			date = (Date)value;
		} else if(isDateObject(value)) {
			date = ((Calendar)value).getTime();
			
		// 以1970年1月1日以后的毫秒构建日期对象
		} else if(isNumber(value)) {
			date = new Date(getDouble0(value).longValue());
			
		// 分数值型字符串和日期字符串构建
		} else if(isString(value)) {
			String s = (String)value;
			if(s.matches("[\\d]+")) {
				date = new Date(getDouble0(value).longValue());
			} else if(s.matches(SteelDate.REGEX_YYYY_MM_DD_HH_MM_SS)) {
				try {
					date = new SimpleDateFormat(SteelDate.YYYY_MM_DD_HH_MM_SS).parse(s);
				} catch (ParseException e) {
					date = new Date();
				}
			} else {
				date = new Date();
			}
		} else {
			date = new Date();
		}
		
		return date;
	} // End getDate
} // End class SteelDataType 
